﻿using System;
using System.Windows;
using System.Windows.Media;
using YiJing.Model;

namespace YiJing.Controls
{
    public class Hexagram : FrameworkElement
    {
        private HexagramFigure _figure = HexagramFigure.FromValue(1);

        #region Value property

        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(Hexagram),
          new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsRender, OnValueChanged));

        public int Value
        {
            get { return (int)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        #endregion

        #region Figure property

        public HexagramFigure Figure
        {
            get { return _figure; }
            private set { _figure = value; }
        }

        #endregion

        #region Spacing property

        public static readonly DependencyProperty SpacingProperty = DependencyProperty.Register("Spacing", typeof(double), typeof(Hexagram),
          new FrameworkPropertyMetadata(0.8, FrameworkPropertyMetadataOptions.AffectsRender, OnGeometryChanged));

        public double Spacing
        {
            get { return (double)GetValue(SpacingProperty); }
            set { SetValue(SpacingProperty, Math.Min(Math.Max(0, value), 1)); }
        }

        #endregion

        #region BreakWidth property

        public static readonly DependencyProperty BreakWidthProperty = DependencyProperty.Register("BreakWidth", typeof(double), typeof(Hexagram),
          new FrameworkPropertyMetadata(0.3, FrameworkPropertyMetadataOptions.AffectsRender, OnGeometryChanged));

        public double BreakWidth {
            get { return (double) GetValue(BreakWidthProperty); }
            set { SetValue(BreakWidthProperty, Math.Min(Math.Max(0, value), 1)); }
        }

        #endregion

        #region UpperTrigram property

        public static readonly DependencyProperty UpperTrigramProperty = DependencyProperty.Register("UpperTrigram", typeof(Brush), typeof(Hexagram),
          new FrameworkPropertyMetadata(Brushes.DarkGray, FrameworkPropertyMetadataOptions.AffectsRender, OnGeometryChanged));

        public Brush UpperTrigram
        {
            get { return (Brush)GetValue(UpperTrigramProperty); }
            set { SetValue(UpperTrigramProperty, value); }
        }

        #endregion

        #region LowerTrigram property

        public static readonly DependencyProperty LowerTrigramProperty = DependencyProperty.Register("LowerTrigram", typeof(Brush), typeof(Hexagram),
          new FrameworkPropertyMetadata(Brushes.DimGray, FrameworkPropertyMetadataOptions.AffectsRender, OnGeometryChanged));

        public Brush LowerTrigram
        {
            get { return (Brush)GetValue(LowerTrigramProperty); }
            set { SetValue(LowerTrigramProperty, value); }
        }

        #endregion

        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);

            var cx = ActualWidth;
            var cxUnit = cx / (2 + BreakWidth);
            var cxOffset = cxUnit * (1 + BreakWidth);
            
            var cy = ActualHeight;
            var cyUnit = cy / (HexagramFigure.MaxLines + (HexagramFigure.MaxLines - 1) * Spacing);
            var cyOffset = cyUnit * (1 + Spacing);

            var lineBounds = new Rect(0, 0, cx, cyUnit);

            if (SnapsToDevicePixels)
            {
                var guidelineSet = new GuidelineSet();

                var y = lineBounds.Y;

                for (var i = 0; i < HexagramFigure.MaxLines; ++i)
                {
                    guidelineSet.GuidelinesY.Add(y);
                    guidelineSet.GuidelinesY.Add(y + lineBounds.Height);

                    y += cyOffset;
                }

                drawingContext.PushGuidelineSet(guidelineSet);
            }

            for (var i = 0; i < HexagramFigure.MaxLines; ++i)
            {
                var fill = i < 3 ? UpperTrigram : LowerTrigram;

                if (_figure.Lines[i].IsBroken)
                {
                    drawingContext.DrawRectangle(fill, null, new Rect(0, lineBounds.Y, cxUnit, lineBounds.Height));
                    drawingContext.DrawRectangle(fill, null, new Rect(cxOffset, lineBounds.Y, cxUnit, lineBounds.Height));
                }
                else
                {
                    drawingContext.DrawRectangle(fill, null, lineBounds);
                }

                lineBounds.Offset(0, cyOffset);
            }

            if (SnapsToDevicePixels)
            {
                drawingContext.Pop();
            }
        }

        private static void OnGeometryChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }

        private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var target = (Hexagram) d;
            target.Figure = HexagramFigure.FromValue(target.Value);
        }
    }
}
